package com.gugee.tiktok.data.consumer.blogger.core.service.impl;

import com.alibaba.nacos.api.config.annotation.NacosValue;
import com.gugee.tiktok.common.model.dal.blogger.BloggerMainRepository;
import com.gugee.tiktok.common.model.dal.blogger.BloggerRepository;
import com.gugee.tiktok.common.model.dal.hashtag.AwemeHashtagRepository;
import com.gugee.tiktok.common.model.dal.hashtag.HashtagRepository;
import com.gugee.tiktok.common.model.dal.mention.AwemeMentionRepository;
import com.gugee.tiktok.common.model.dal.music.MusicRepository;
import com.gugee.tiktok.common.model.mysql.*;
import com.gugee.tiktok.common.model.spider.aweme.Aweme_list;
import com.gugee.tiktok.common.model.spider.aweme.Text_extra;
import com.gugee.tiktok.data.consumer.blogger.config.DataConsumerConfig;
import com.gugee.tiktok.data.consumer.blogger.core.service.CollectService;
import io.micrometer.core.instrument.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: luolifeng
 * Date: 2020-10-16 9:21
 */
@Service
@Slf4j
public class CollectServiceImpl implements CollectService {
    @Autowired
    MusicRepository musicRepository;
    @Autowired
    DataConsumerConfig dataConsumerConfig;
    @Autowired
    Hashtag.HashTagMapper hashTagMapper;
    @Autowired
    HashtagRepository hashTagRepository;
    @Autowired
    AwemeHashtagRepository awemeHashtagRepository;
    @Autowired
    BloggerRepository bloggerRepository;
    @Autowired
    AwemeMentionRepository awemeMentionRepository;
    @Autowired
    BloggerMainRepository bloggerMainRepository;
    @Autowired
    DataConsumerConfig consumerConfig;


    /**
     * 使用了hashmap来做去重处理
     * @param awemeList 爬取到的数据
     */
    public void collectMusic(List<Aweme_list> awemeList) {
        long secondsNday=3600*24* dataConsumerConfig.getHashtagClDays();
        Map<Long, Aweme_list> musicIdAwemeMap=new HashMap<>(awemeList.size());
        //去重，多个视频可能用了同一音乐
        for(Aweme_list e:awemeList){
            if(e.getCreate_time()< System.currentTimeMillis()/1000L-secondsNday){
                continue;
            }
            if(!musicIdAwemeMap.containsKey(e.getMusic().getMid())){
                musicIdAwemeMap.put(e.getMusic().getMid(),e);
            }
        }
        if(musicIdAwemeMap.size()==0){
            return;
        }
        //查询出已存在Music
        List<Music> existsMusics=   batchQueryMusic(new ArrayList<>(musicIdAwemeMap.keySet()));
        //去除已存在
        existsMusics.forEach(e->{
                    musicIdAwemeMap.remove(e.getMid());
                }
            );
        if(musicIdAwemeMap.size()==0){
            return;
        }
        List<Aweme_list>  inserts=new ArrayList<>(musicIdAwemeMap.values());
//            Map<Long, Music> existsMusicMap = existsMusics.stream().collect(Collectors.toMap(Music::getMid, a -> a,(k1, k2)->k1));
        musicRepository.batchSaveMusicFromAwemes(inserts);
    }

    @Override
    public void collectHashTag(List<Aweme_list> awemeList) {
        long secondsNday=3600*24* dataConsumerConfig.getHashtagClDays();
        Map<Long, Text_extra> hashtagIdAwemeMap=new HashMap<>(awemeList.size());
        for(Aweme_list e:awemeList){
            if(e.getCreate_time()< System.currentTimeMillis()/1000L-secondsNday){
                continue;
            }
            for(Text_extra textExtra:e.getText_extra()){
                hashtagIdAwemeMap.put(textExtra.getHashtag_id(),textExtra);
            }
        }
        if(hashtagIdAwemeMap.size()==0){
            return;
        }

        //查询出已存在hashtag
        List<Hashtag> existsHashtags = batchQueryHashtag(new ArrayList<>(hashtagIdAwemeMap.keySet()));
        existsHashtags.forEach(e->{
            hashtagIdAwemeMap.remove(e.getHid());
        });
        if(hashtagIdAwemeMap.size()==0){
            return;
        }
        hashTagRepository.batchSaveHashTag(new ArrayList<>(hashtagIdAwemeMap.values()));


    }
    @Override
    public void collectAwemeMap2HashTag(List<Aweme_list> awemeList,Long uid) {
        List<AwemeHashtag> awemeHashtags=new ArrayList<>(awemeList.size());
        List<Long> awemeIds=new   ArrayList<>(awemeList.size());
        long secondsNday=3600*24* dataConsumerConfig.getHashtagClDays();
        for(Aweme_list e:awemeList){
            //todo 需保证N天可轮询一周期
            if(e.getCreate_time()< System.currentTimeMillis()/1000L-secondsNday){
                continue;
            }
            long awemeId=Long.parseLong(e.getAweme_id());
            awemeIds.add(awemeId);
            for(Text_extra textExtra:e.getText_extra()){
                if(StringUtils.isEmpty(textExtra.getHashtag_name())){
                    continue;
                }
                AwemeHashtag awemeHashtag=new AwemeHashtag();
                awemeHashtag.setHid(textExtra.getHashtag_id());
                awemeHashtag.setAwemeId(awemeId);
                awemeHashtag.setHashtagName(textExtra.getHashtag_name());
                awemeHashtag.setCommerce(textExtra.isCommerce());
                awemeHashtag.setUid(uid);
                awemeHashtag.setCreateTime(e.getCreate_time());
                awemeHashtags.add(awemeHashtag);
            }
        }
        if(awemeHashtags.size()==0){
            return;
        }

        //查询出已存在AwemeHashtag
        List<AwemeHashtag> existsAwemeHashtags = awemeHashtagRepository.findByAwemeIdIn(awemeIds);


        Map<String, AwemeHashtag> existsAwemeHashtagMap = existsAwemeHashtags.stream().collect(Collectors.toMap(AwemeHashtag::getUniqueId, a -> a,(k1, k2)->k1));

        List<AwemeHashtag> insertAwemeHashtags=awemeHashtags.stream().filter(awemeHashtag -> !existsAwemeHashtagMap.containsKey(awemeHashtag.getUniqueId())).collect(Collectors.toList());
        if(insertAwemeHashtags.size()==0){
            return;
        }
        awemeHashtagRepository.batchSaveAwemeHashtag(insertAwemeHashtags);

    }

    @Override
    public void collectAwemeMap2Mention(List<Aweme_list> awemeList, Long uid) {
        long startTime = System.currentTimeMillis();
//        log.info("==============开始收集提及用户信息！");
        List<AwemeMention> awemeMentions = new ArrayList<>(awemeList.size());
        List<Long> awemeIds = new ArrayList<>(awemeList.size());
        long secondsNday=3600*24* dataConsumerConfig.getHashtagClDays();
        for (Aweme_list a : awemeList) {
            if(a.getCreate_time()< System.currentTimeMillis()/1000L-secondsNday){
                continue;
            }

            if(!a.getDesc().contains("@")){
                continue;
            }

            String [] descs = a.getDesc().split(" ");
            Long awemeId = Long.parseLong(a.getAweme_id());
            awemeIds.add(awemeId);
            for (String desc : descs) {
                if(desc.startsWith("@") && desc.length() > 1){
                    //Optional<Blogger> blogger = bloggerRepository.findByoUniqueId(desc.substring(1));
                    Optional<BloggerMain> blogger;
                    try{
                        blogger = bloggerMainRepository.findByoUniqueId(desc.substring(1));
                    }catch (IncorrectResultSizeDataAccessException e){
                        log.error("有重覆的uniqueId:{}",desc.substring(1));
                        continue;
                    }

                    AwemeMention awemeMention = new AwemeMention();
                    awemeMention.setMentionUniqueId(desc.substring(1));
                    awemeMention.setAwemeCreateTime(a.getCreate_time());
                    awemeMention.setUid(uid);
                    awemeMention.setAwemeId(awemeId);
                    if(blogger.isPresent()){
                        awemeMention.setMentionUid(blogger.get().getOUid());
                        awemeMention.setMentionAvatar(blogger.get().getOAvatar168());
                        awemeMention.setMentionNickname(blogger.get().getONickname());
                        awemeMention.setMentionCustomVerify(blogger.get().getCustomVerify());
                        awemeMention.setMentionEnterpriseVerifyReason(blogger.get().getEnterpriseVerifyReason());
                    }
                    awemeMentions.add(awemeMention);
                }
            }
        }

        if(awemeIds.size() == 0){
            return;
        }
        long findInSaveStartTime = System.currentTimeMillis();
        List<AwemeMention> existsMentions = awemeMentionRepository.findByAwemeIdIn(awemeIds);
        if((System.currentTimeMillis() - findInSaveStartTime) /1000 > dataConsumerConfig.getMentionDebugTimeLimit()){
            log.info("==============提及IN查询MYSQL用时{}秒",(System.currentTimeMillis() - findInSaveStartTime) /1000);
        }

        Map<String,AwemeMention> existsMentionMap = existsMentions.stream().collect(Collectors.toMap(AwemeMention::getUniqueId, a->a,(k1, k2)->k1));

        List<AwemeMention> insertAwemeMentions=awemeMentions.stream().filter(awemeMention -> !existsMentionMap.containsKey(awemeMention.getUniqueId())).collect(Collectors.toList());

        if(insertAwemeMentions.size() == 0){
            return;
        }
        long bachSaveStartTime = System.currentTimeMillis();
        awemeMentionRepository.batchSaveAwemeMention(insertAwemeMentions);
        if((System.currentTimeMillis() - bachSaveStartTime) /1000 > dataConsumerConfig.getMentionDebugTimeLimit()){
            log.info("==============批量保存{}个提及数据到MYSQL用时{}秒,总用时{}秒",insertAwemeMentions.size(),(System.currentTimeMillis() - bachSaveStartTime) /1000,(System.currentTimeMillis() - startTime) /1000);
        }
    }


    public List<Hashtag> batchQueryHashtag(List<Long> ids){
        int batchNums=dataConsumerConfig.getBatchNums();
        if(ids.size()<=batchNums){
            return hashTagRepository.findByHidIn(ids);
        }

        int cnt=0;
        List<Long> tmpIds=new ArrayList<>(batchNums);
        List<Hashtag> rst=new ArrayList<>(ids.size());

        for (Long e : ids) {
            tmpIds.add(e);
            cnt++;
            if(cnt%batchNums==0){
                rst.addAll(hashTagRepository.findByHidIn(tmpIds)) ;
                cnt=0;
                tmpIds.clear();
            }
        }
        //剩余
        if(cnt>0){
            rst.addAll(hashTagRepository.findByHidIn(tmpIds)) ;
            tmpIds.clear();
        }
        return rst;
    }
    public List<Music> batchQueryMusic(List<Long> ids){
        int batchNums=dataConsumerConfig.getBatchNums();
        if(ids.size()<=batchNums){
            return musicRepository.findByMidIn(ids);
        }

        int cnt=0;
        List<Long> tmpIds=new ArrayList<>(batchNums);
        List<Music> rst=new ArrayList<>(ids.size());

        for (Long e : ids) {
            tmpIds.add(e);
            cnt++;
            if(cnt%batchNums==0){
                rst.addAll(musicRepository.findByMidIn(tmpIds)) ;
                cnt=0;
                tmpIds.clear();
            }
        }
        //剩余
        if(cnt>0){
            rst.addAll(musicRepository.findByMidIn(tmpIds)) ;
            tmpIds.clear();
        }
        return rst;
    }
}
